﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using Hrm.Services;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Security;
using System.Security.Claims;
using System.Web.Security;
using System.Security.Cryptography;
using Hrm.Core;
using System.Security.Principal;
using Hrm.Web.Framework;

namespace Hrm.Web.Controllers
{
    public class AdminController : Controller
    {
        IResourceService _resourceService;
        IUserService _userService;
        IRoleService _roleService;
        ICacheManager _cacheManager;
        public AdminController(IResourceService resourceService, IUserService userService, IRoleService roleService, ICacheManager cacheManager)
        {
            this._resourceService = resourceService;
            this._userService = userService;
            this._roleService = roleService;
            this._cacheManager = cacheManager;
        }

        [Authorize]
        public ActionResult Index()
        {
            ViewBag.UserName = User.Identity.Name;
            return View();
        }

        [Authorize]
        public PartialViewResult Menu()
        {
            string roleCodeStr = string.Empty;
            List<string> roleCodes = new List<string>();
            var data = HttpContext.Request.GetOwinContext().Authentication.User.Claims;
            var entity = data.FirstOrDefault(a => a.Type == ClaimTypes.Role);
            if (entity != null)
            {
                roleCodeStr = entity.Value;
                roleCodes = roleCodeStr.Split(',').ToList();
            }

            string cacheStr = string.Format(Constant.CacheMenu, roleCodeStr);
            var resources = this._cacheManager.Get<IEnumerable<ResourceShowDto>>(cacheStr);
            if (resources == null)
            {
                resources = this._resourceService.GetResourceToShow(Constant.CurrentAppId, Constant.RourseMenuType, roleCodes);
                this._cacheManager.Set(cacheStr, resources, Constant.CacheTimeout);
            }
            return PartialView("_Menu", resources);
        }

        [AllowAnonymous]
        public ActionResult Login(string returnUrl)
        {
            ViewBag.ReturnUrl = returnUrl;
            var model = new LoginViewModel();
            return View(model);
        }

        [HttpPost]
        [AllowAnonymous]
        public ActionResult Login(LoginViewModel model)
        {
            var url=Request.Url;
            if (ModelState.IsValid)
            {
                string password = EncryptionTool.getMd5(model.Password);
                var user = _userService.GetPerson(model.UserName, password);
                if (user != null)
                {
                    SignInAsync(user, model.RememberMe=="on");
                    GlobalQueue.LogQueue.Enqueue(new Log()
                    {
                        Origin = "/Admin/Login",
                        Level = (int)EnumLogLevel.Trace,
                        Message = user.Name+"登录成功",
                        StackTrade = string.Empty,
                        CreateDatetime = DateTime.Now,
                        CreateUserCode = user.Code
                    });
                    if (user.Url!=null)
                        return RedirectToLocal(user.Url);
                    return RedirectToLocal(model.ReturnUrl);//ReturnUrl
                }
                else
                {
                    ModelState.AddModelError("", "你的用户名或者密码错误！");
                }
            }

            // 如果我们进行到这一步时某个地方出错，则重新显示表单
            return View(model);
        }

        [Authorize]
        public ActionResult LogOff()
        {
            AuthenticationManager.SignOut();
            return RedirectToAction("Index", "Admin");
        }

        [Authorize]
        public ActionResult ModifyPassword()
        {
            return View();
        }

        [HttpPost]
        public ActionResult ModifyPassword(ModifyPasswordDto model)
        {
            if (model.OldPassword==model.NewPassword)
            {
                ModelState.AddModelError("NewPassword", "新旧密码不能相同！");
            }
            if (ModelState.IsValid)
            {
                var userCode = User.Identity.GetUserId();
                string oldPassword = EncryptionTool.getMd5(model.OldPassword);
                var user = this._userService.GetPerson(userCode);
                if (user != null && user.Password == oldPassword)
                {
                    user.Password = EncryptionTool.getMd5(model.NewPassword);
                    this._userService.Update(user);
                    return RedirectToAction("Index", "Admin");
                }
                else
                {
                    ModelState.AddModelError("OldPassword", "原密码错误！");
                }
            }
            return View(model);
        }

        private IAuthenticationManager AuthenticationManager
        {
            get
            {
                return HttpContext.GetOwinContext().Authentication;
            }
        }

        private void SignInAsync(UserDto user, bool isPersistent)
        {
            var roles = this._roleService.GetRoleCodesByUserCode(user.Code);
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            var identity = new ClaimsIdentity(new[]
                {
                    new Claim(ClaimTypes.Name,user.Name),
                    new Claim(ClaimTypes.NameIdentifier,user.Code),
                    new Claim(ClaimTypes.Role,string.Join<string>(",",roles))
                }, DefaultAuthenticationTypes.ApplicationCookie);
            AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
        }

        private ActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Admin");
            }
        }
    }
}